package com.intel.factorytest.activity;

import java.io.File;
import java.io.IOException;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

public class Recorder_IntelMAT implements OnCompletionListener, OnErrorListener, MediaRecorder.OnInfoListener {
    static final String Intel_MAT_SAMPLE_PREFIX = "recording";
    static final String Intel_MAT_SAMPLE_PATH_KEY = "sample_path";
    static final String Intel_MAT_SAMPLE_LENGTH_KEY = "sample_length";
    public static final int Intel_MAT_NO_SDCARD = -1;
    public static final int Intel_MAT_IDLE_STATE = 0;
    public static final int Intel_MAT_RECORDING_STATE = 1;
    public static final int Intel_MAT_STOPE_RECORDING_STATE = 2;
    public static final int Intel_MAT_PLAYING_STATE = 3;
    public static final int Intel_MAT_STOPE_PLAYING_STATE = 4;
    public static final int Intel_MAT_max_duration_ms = 5000; // 5s
    
    public boolean intel_MAT_mPlayBackIsCompleted = false;
    public boolean intel_MAT_mIsPlaying = false;
    public boolean intel_MAT_mIsRecording = false;
    public boolean intel_MAT_mMaxDurationReached = false;
    int mState = Intel_MAT_NO_SDCARD;

    public static final int Intel_MAT_NO_ERROR = 0;
    public static final int Intel_MAT_SDCARD_ACCESS_ERROR = 1;
    public static final int Intel_MAT_INTERNAL_ERROR = 2;
    
    static final String TAG = "Recorder";   

    public interface OnStateChangedListener {
        public void onStateChanged(int state);
        public void onError(int error);
    }
    OnStateChangedListener intel_MAT_mOnStateChangedListener = null;
    
    long intel_MAT_mSampleStart = 0;       // time at which latest record or play operation started
    int intel_MAT_mSampleLength = 0;      // length of current sample
    File intel_MAT_mSampleFile = null;
    
    MediaRecorder intel_MAT_mRecorder = null;
    MediaPlayer intel_MAT_mPlayer = null;
    
    public Recorder_IntelMAT() {
        if (intel_MAT_mSampleFile == null) {
        File sampleDir = Environment.getDataDirectory();
        Log.d(TAG,"recorder === "+sampleDir.canWrite()); 
        if (true == sampleDir.canWrite()) { 
            setState_MAT(Intel_MAT_IDLE_STATE);
        }
    }
    }
        
    public void saveState_MAT(Bundle recorderState) {
        recorderState.putString(Intel_MAT_SAMPLE_PATH_KEY, intel_MAT_mSampleFile.getAbsolutePath());
        recorderState.putInt(Intel_MAT_SAMPLE_LENGTH_KEY, intel_MAT_mSampleLength);
    }
    
    public int getMaxAmplitude_MAT() {
        if (mState != Intel_MAT_RECORDING_STATE)
            return 0;
        return intel_MAT_mRecorder.getMaxAmplitude();
    }
    
    public void restoreState_MAT(Bundle recorderState) {
        String intel_MAT_samplePath = recorderState.getString(Intel_MAT_SAMPLE_PATH_KEY);
        if (intel_MAT_samplePath == null)
            return;
        int intel_MAT_sampleLength = recorderState.getInt(Intel_MAT_SAMPLE_LENGTH_KEY, -1);
        if (intel_MAT_sampleLength == -1)
            return;

        File file = new File(intel_MAT_samplePath);
        if (!file.exists())
            return;
        if (intel_MAT_mSampleFile != null
                && intel_MAT_mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0)
            return;
        
        delete_MAT();
        intel_MAT_mSampleFile = file;
        intel_MAT_mSampleLength = intel_MAT_sampleLength;

        signalStateChanged_MAT(Intel_MAT_IDLE_STATE);
    }
    
    public void setOnStateChangedListener_MAT(OnStateChangedListener listener) {
        intel_MAT_mOnStateChangedListener = listener;
    }
    
    public int state_MAT() {
        return mState;
    }
    
    public int progress_MAT() {
        if (mState == Intel_MAT_RECORDING_STATE || mState == Intel_MAT_PLAYING_STATE)
            return (int) ((System.currentTimeMillis() - intel_MAT_mSampleStart)/1000);
        return 0;
    }
    
    public int sampleLength_MAT() {
        return intel_MAT_mSampleLength;
    }

    public File sampleFile_MAT() {
        return intel_MAT_mSampleFile;
    }
    
    /**
     * Resets the recorder state. If a sample was recorded, the file is deleted.
     */
    public void delete_MAT() {
        stop();
        
        if (intel_MAT_mSampleFile != null)
            intel_MAT_mSampleFile.delete();

        intel_MAT_mSampleFile = null;
        intel_MAT_mSampleLength = 0;
        
        signalStateChanged_MAT(Intel_MAT_IDLE_STATE);
    }
    
    public void clear() {
        stop();
        
        intel_MAT_mSampleLength = 0;
        
        signalStateChanged_MAT(Intel_MAT_IDLE_STATE);
    }
    
    public synchronized void startRecording_MAT(int outputfileformat, String extension, int audiosourcetype, int codectype) {
           Log.d(TAG,"startRecording !!!");
        stop();
        if (intel_MAT_mSampleFile == null) {

        File intel_MAT_sampleDir = Environment.getDataDirectory();
        Log.d(TAG,"recorder === "+intel_MAT_sampleDir.canWrite()); 
        intel_MAT_sampleDir = new File("/data/data/com.intel.factorytest/");
        if (!intel_MAT_sampleDir.exists()) {
            intel_MAT_sampleDir.mkdirs();
        }
        Log.d(TAG,"cyj recorder === "+intel_MAT_sampleDir.canWrite()); 
        try {
            intel_MAT_mSampleFile = File.createTempFile(Intel_MAT_SAMPLE_PREFIX, extension, intel_MAT_sampleDir);
        } catch (IOException e) {
            Log.d(TAG,"startRecording 11");
            setError_MAT(Intel_MAT_SDCARD_ACCESS_ERROR);
            return;
        }
    }
    Process proc;
    int sta;
    try {
        proc = Runtime.getRuntime().exec("chmod 777 " +  intel_MAT_mSampleFile);
        sta = proc.waitFor();  
        if (sta == 0) {
            Log.e(TAG,"ok success!!");
        }   
    }catch (IOException e) {
        Log.d(TAG,"startRecording ioerror");
        setError_MAT(Intel_MAT_SDCARD_ACCESS_ERROR);
        return;
    }catch (InterruptedException e) {
        return;
    }

        intel_MAT_mRecorder = new MediaRecorder();
        intel_MAT_mRecorder.setAudioSource(audiosourcetype);
        intel_MAT_mRecorder.setOutputFormat(outputfileformat);
        intel_MAT_mRecorder.setAudioEncoder(codectype);
        intel_MAT_mRecorder.setOutputFile(intel_MAT_mSampleFile.getAbsolutePath());
        intel_MAT_mRecorder.setMaxDuration(Intel_MAT_max_duration_ms);
        // register listener for max duration is reached
        intel_MAT_mRecorder.setOnInfoListener(this);

        // Handle IOException
        try {
            intel_MAT_mRecorder.prepare();
        } catch(IOException exception) {
            setError_MAT(Intel_MAT_INTERNAL_ERROR);
        Log.d(TAG,"startRecording !!");
            intel_MAT_mRecorder.reset();
            intel_MAT_mRecorder.release();
            intel_MAT_mRecorder = null;
            return;
        }
        intel_MAT_mRecorder.start();
        
        intel_MAT_mIsRecording = true;

        intel_MAT_mSampleStart = System.currentTimeMillis();
           Log.d(TAG,"startRecording mSampleStart ="+intel_MAT_mSampleStart);
        setState_MAT(Intel_MAT_RECORDING_STATE);
    }
    
    public synchronized void stopRecording_MAT() {
        if (intel_MAT_mRecorder == null)
            return;

        intel_MAT_mIsRecording = false;
        intel_MAT_mRecorder.stop();
        intel_MAT_mRecorder.reset();
        intel_MAT_mRecorder.release();
        intel_MAT_mRecorder = null;

        intel_MAT_mSampleLength = (int)( (System.currentTimeMillis() - intel_MAT_mSampleStart)/1000 );
        setState_MAT(Intel_MAT_STOPE_RECORDING_STATE);
    }
    
    public synchronized void startPlayback_MAT() {
        stop();
    intel_MAT_mPlayBackIsCompleted = false;
    intel_MAT_mIsPlaying = true;
    Log.d(TAG,"startPlayback !!!!!!!!");
        intel_MAT_mPlayer = new MediaPlayer();
        try {
            intel_MAT_mPlayer.setDataSource(intel_MAT_mSampleFile.getAbsolutePath());
          //  mPlayer.setDataSource("/local/test/recording1823344811.amr");
            intel_MAT_mPlayer.setOnCompletionListener(this);
            intel_MAT_mPlayer.setOnErrorListener(this);
            intel_MAT_mPlayer.prepare();
            intel_MAT_mPlayer.start();
        } catch (IllegalArgumentException e) {
            setError_MAT(Intel_MAT_INTERNAL_ERROR);
            intel_MAT_mPlayer = null;
            return;
        } catch (IOException e) {
        e.printStackTrace(); 
        setError_MAT(Intel_MAT_SDCARD_ACCESS_ERROR);
        intel_MAT_mPlayer = null;
        return;
        }
        
        intel_MAT_mSampleStart = System.currentTimeMillis();
        setState_MAT(Intel_MAT_PLAYING_STATE);
    }
    
    public synchronized void stopPlayback_MAT() {
        if (intel_MAT_mPlayer == null) // we were not in playback
            return;

        intel_MAT_mPlayer.stop();
        intel_MAT_mPlayer.release();
        intel_MAT_mPlayer = null;
        setState_MAT(Intel_MAT_STOPE_PLAYING_STATE);
    }
    
    public void stop() {
        stopRecording_MAT();
        stopPlayback_MAT();
        setState_MAT(Intel_MAT_IDLE_STATE);
    }

    public boolean onError(MediaPlayer mp, int what, int extra) {
        stop();
        setError_MAT(Intel_MAT_SDCARD_ACCESS_ERROR);
        return true;
    }

    public void onCompletion(MediaPlayer mp) {
        Log.d(TAG,"tangjun onCompletion");
        stop();
    intel_MAT_mPlayBackIsCompleted = true;
    intel_MAT_mIsPlaying = false;
    }
    
    private void setState_MAT(int state) {
           Log.d(TAG,"setState mState ="+mState+"sstate ="+state);
        if (state == mState)
            return;
        
        mState = state;
        signalStateChanged_MAT(mState);
    }
    public int getState_MAT(){
        return mState;
    }
    private void signalStateChanged_MAT(int state) {
        if (intel_MAT_mOnStateChangedListener != null)
            intel_MAT_mOnStateChangedListener.onStateChanged(state);
    }
    
    private void setError_MAT(int error) {
        if (intel_MAT_mOnStateChangedListener != null)
            intel_MAT_mOnStateChangedListener.onError(error);
    }

    @Override
    public void onInfo(MediaRecorder mr, int what, int extra) {
        // TODO Auto-generated method stub
        switch (what) {
        case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:
            // automaticlly play when max duration is reached
            Log.d(TAG,"tangjun max duration reached");
            intel_MAT_mMaxDurationReached = true;
            stopRecording_MAT();
            startPlayback_MAT();
            break;

        default:
            break;
        }
    }
}
